package com.xiaofengstu.mcams.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @Author FengZeng
 * @Date 2022-05-10 20:45
 * @Description TODO
 */
@Slf4j
@Component
public class RedisUtils {
  /**
   * 自定 key 三种 String key:String value
   * 普通key:value String
   * key:Set<String> set key:set 集合 String
   * key:List<String> list key:list 集合
   */
  private static final String KEY_PREFIX_KEY = "info:bear:key";
  private static final String KEY_PREFIX_SET = "info:bear:set";
  private static final String KEY_PREFIX_LIST = "info:bear:list";

  private final RedisTemplate<String, String> redisTemplate;

  public RedisUtils(RedisTemplate<String, String> redisTemplate) {
    this.redisTemplate = redisTemplate;
  }


  public long getExpire(String key) {
    return redisTemplate.getExpire(KEY_PREFIX_KEY+key);
  }


  public boolean cacheValue(String k, String v, long time) {
    try {
      String key = KEY_PREFIX_KEY + k;
      ValueOperations<String, String> ops = redisTemplate.opsForValue();
      ops.set(key, v);
      if (time > 0) {
        redisTemplate.expire(key, time, TimeUnit.SECONDS);
      }
      return true;
    } catch (Throwable e) {
      log.error("缓存存入失败，key:[{}], value:[{}]", k, v);
    }
    return false;
  }


  public boolean cacheValue(String key, String value) {
    return cacheValue(key, value, -1);
  }


  public boolean containsValueKey(String key) {
    return containsKey(KEY_PREFIX_KEY + key);
  }


  public boolean containsSetKey(String key) {
    return containsKey(KEY_PREFIX_KEY + key);
  }


  public boolean containsListKey(String key) {
    return containsKey(KEY_PREFIX_KEY + key);
  }


  public boolean containsKey(String key) {
    try {
      return Boolean.TRUE.equals(redisTemplate.hasKey(key));
    } catch (Throwable ex) {
      log.error("判断缓存失败,key:" + key + "，错误信息:" + ex);
    }
    return false;
  }


  public String getValue(String k) {
    try {
      String key = KEY_PREFIX_KEY + k;
      ValueOperations<String, String> ops = redisTemplate.opsForValue();
      return ops.get(key);
    } catch (Throwable ex) {
      log.error("根据key获取缓存失败,key" + k + ", 失败原因：" + ex);
    }
    return null;
  }


  public boolean removeValue(String key) {
    return remove(KEY_PREFIX_KEY + key);
  }

  private boolean remove(String k) {
    try {
      redisTemplate.delete(k);
      return true;
    } catch (Throwable ex) {
      log.error("移除缓存失败 key:[{}] 失败原因 [{}]", k, ex);
    }
    return false;
  }


  public boolean removeSet(String key) {
    return remove(KEY_PREFIX_SET + key);
  }


  public boolean removeList(String key) {
    return remove(KEY_PREFIX_LIST + key);
  }


  public boolean cacheSet(String k, String v, long time) {
    try {
      String key = KEY_PREFIX_SET + k;
      SetOperations<String, String> opsForSet = redisTemplate.opsForSet();
      opsForSet.add(key, v);
      if (time > 0) {
        redisTemplate.expire(key, time, TimeUnit.SECONDS);
      }
      return true;
    } catch (Throwable ex) {
      log.error("缓存set失败，当前key: " + k + " , value: " + v);
    }
    return false;
  }


  public boolean cacheSet(String key, String value) {
    return cacheSet(key, value, -1);
  }


  public boolean cacheSet(String k, Set<String> v, long time) {
    try {
      String key = KEY_PREFIX_SET + k;
      SetOperations<String, String> opsForSet = redisTemplate.opsForSet();
      opsForSet.add(key, v.toArray(v.toArray(new String[v.size()])));
      if (time > 0) {
        redisTemplate.expire(key, time, TimeUnit.SECONDS);
      }
      return true;
    } catch (Throwable ex) {
      log.error("缓存Set失败，当前key: " + k + ", 失败原因: " + ex);
    }
    return false;
  }


  public boolean cacheSet(String key, Set<String> value) {
    return cacheSet(key, value, -1);
  }


  public Set<String> getSet(String k) {
    try {
      String key = KEY_PREFIX_SET + k;
      SetOperations<String, String> opsForSet = redisTemplate.opsForSet();
      return opsForSet.members(key);
    } catch (Throwable ex) {
      log.error("获取缓存Set失败，当前 key:" + k);
    }
    return null;
  }


  public boolean cacheList(String k, String value, long time) {
    try {
      String key = KEY_PREFIX_LIST + k;
      ListOperations<String, String> opsForList = redisTemplate.opsForList();
      opsForList.rightPush(key, value);
      if (time > 0) {
        redisTemplate.expire(key, time, TimeUnit.SECONDS);
      }
      return true;
    } catch (Throwable ex) {
      log.error("缓存list失败， 当前key：" + k + ", 失败原因: " + ex);

    }
    return false;
  }


  public boolean cacheList(String key, String value) {
    return cacheList(key, value, -1);
  }


  public boolean cacheList(String k, List<String> value, long time) {
    try {
      String key = KEY_PREFIX_LIST + k;
      ListOperations<String, String> opsForList = redisTemplate.opsForList();
      opsForList.rightPushAll(key, value);
      if (time > 0) {
        redisTemplate.expire(key, time, TimeUnit.SECONDS);
      }
      return true;
    } catch (Throwable ex) {
      log.error("缓存list失败，当前key: " + k + ", 失败原因： " + ex);
    }
    return false;
  }


  public List<String> getList(String k, long start, long end) {
    try {
      String key = KEY_PREFIX_LIST + k;
      ListOperations<String, String> opsForList = redisTemplate.opsForList();
      return opsForList.range(k, start, end);
    } catch (Throwable ex) {
      log.error("缓存list失败，当前key: " + k + ", 失败原因： " + ex);
    }
    return null;
  }


  public long getListSize(String key) {
    try {
      ListOperations<String, String> opsForList = redisTemplate.opsForList();
      return opsForList.size(KEY_PREFIX_LIST + key);
    } catch (Throwable ex) {
      log.error("获取list长度失败, key: " + key + ", 失败原因：" + ex);
    }
    return 0;
  }


  public long getListSize(ListOperations<String, String> listOps, String key) {
    try {
      return listOps.size(key);
    } catch (Throwable ex) {
      log.error("获取list长度失败，当前key： " + key + "， 失败原因：" + ex);
    }
    return 0;
  }


  public boolean removeOneOfList(String k) {
    try {
      String key = KEY_PREFIX_LIST + k;
      ListOperations<String, String> opsForList = redisTemplate.opsForList();
      opsForList.leftPop(key);
      return true;
    } catch (Throwable ex) {
      log.error("移除list缓存失败，当前key：" + k + "， 失败原因：" + ex);
    }
    return false;
  }
}
